home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
gtar_hlp.zip
/
FRETBD.C
< prev
next >
Wrap
Text File
|
1990-01-15
|
12KB
|
365 lines
/*
Subj: Guitarist's Helper
Fellow guitarists/bassists:
I wrote a program that prints a guitar fretboard diagram, and
labels notes or patterns according command-line args. I found it
helpful in learning and scales and patterns.
The user can specify scale notes directly, or supply a root and
formula for a scale. Positions on the fretboard diagram may be labled
with a user-defined character if desired (this is good for learning
patterns as opposed to actual note names). Here's a sample output:
synapse /betty/b3/fcg 17> fretbd -i G# 2 2 1 2 2 2
Scale = G# A# C C# D# F G
+ + + + + + + + + +
-||-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|
-||-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|
G||-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|
-||-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|
-||-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|
-||-F-|---|-G-|-G#|---|-A#|---|-C-|-C#|---|-D#|---|-F-|---|-G-|-G#|---|-A#|---|
This is my first posting of code to the net; any comments or
suggestions are welcome. Please use e-mail replies where appropriate.
- Yours truly
*/
/* ********************************************************************** */
/*
* FILE: fretbd.2.c
* AUTHOR: Frank C. Guida Philips Laboratories
* (fcg@philabs.philips.com) Briarcliff Manor, NY 10510
*
* DATE: Fri Dec 22 10:49:29 1989
*
* Please acknowledge the author in any reproduction or modification.
*
* SYNOPSIS: fretbd [-h] [-s] [-m char]
* [-i root interval_list] | [-n note_list]
*
* DESCRIPTION: fretbd prints a guitar fretboard (20 frets)
* and labels notes according to the command-line
* args. Notes may be entered in upper or lower
* case; use b or # to indicate accidentals.
*
* OPTION SUMMARY: (no args): print blank fretboard.
* -h: print this message.
* -s: use sharps instead of flats as the
* dflt_note_type (use with -i option).
* -m: use char to mark note positions as
* opposed to letter names.
* -i: construct scale using specified root
* and intervals (in half-steps).
* -n: construct scale using specified notes.
*
* EXAMPLE: to print the F#maj scale -
* host> fretbd -i F# 2 2 1 2 2 2
*
*/
/* ********************************************************************** */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define HELP_MESSAGE "\
Use: fretbd [-h] [-s] [-m char] [-i root interval_list] | [-n note_list]\n\n\
Option Summary: (no args): print blank fretboard.\n\
-h: print this message.\n\
-s: use sharps instead of flats as the\n\
dflt_note_type (use with -i option).\n\
-m: use char to mark note positions as\n\
opposed to letter names.\n\
-i: construct scale using specified root\n\
and intervals (in half-steps).\n\
-n: construct scale using specified notes.\n"
#define OP_HELP "-h"
#define OP_SHARPS "-s"
#define OP_POS_MARK "-m"
#define OP_INTERVALS "-i"
#define OP_NOTES "-n"
#define NUM_FRETS 20 /* numbered 0-19 */
#define NUM_STRINGS 6 /* numbered 1-6 */
#define MAX_NOTES 12
#define FLATS 0
#define SHARPS 1
#define NECK_INDEX "\
+ + + + + + +\
+ + +\n"
/* Basic macros */
#define streq(s1, s2) (strcmp(s1, s2) == 0)
#define not_option(arg) !(streq(arg, OP_HELP) ||\
streq(arg, OP_SHARPS) ||\
streq(arg, OP_POS_MARK) ||\
streq(arg, OP_INTERVALS) ||\
streq(arg, OP_NOTES))
/* function declarations */
char *get_note();
short note_index();
void error();
void print_fretbd();
void print_note();
/* global variables */
static char *chrom[2][12] =
{ /* 1 2 3 4 5 6 7 */
{"C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B"},
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
{"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"}
};
char pos_mark_char = '\0';
unsigned short note_type;
unsigned short num_notes = 0;
/* ********************************************************************** */
main( argc, argv )
int argc;
char *argv[];
{
char *scale[MAX_NOTES];
short note_idx;
unsigned short a, i, interval;
unsigned short dflt_note_type = FLATS;
for( i=0; i < MAX_NOTES; i++ ) /* initialize scale array */
scale[i] = "-";
/* Parse and verify command-line args. Args are checked for
* consistency with any associated option flag (i.e. if the -i option
* is given, the following arg should be a valid note name, and
* subsequent args should be valid intervals or a new option flag).
*/
for( a=1; a < argc; a++ )
{
if( streq(argv[a], OP_HELP) )
error( "", "" ); /* not really an error */
else if( streq(argv[a], OP_SHARPS) )
dflt_note_type = SHARPS;
else if( streq(argv[a], OP_POS_MARK) )
{
if( (a+1 < argc) && not_option(argv[a+1]) )
sscanf( argv[++a], "%c", &pos_mark_char );
else
error( "", "Specify one character for position mark." );
}
else if( streq(argv[a], OP_INTERVALS) )
{
i = 0;
while( (a+1 < argc) && not_option(argv[a+1]) )
{
if( i == 0 ) /* first arg to -i option should be name of root */
{
/* convert case if needed */
if( islower(*(argv[++a])) )
*(argv[a]) = toupper( *(argv[a]) );
if( (note_idx = note_index(argv[a])) >= 0 ) /* valid note? */
{
scale[i++] = chrom[note_type][note_idx];
/* if root is an accidental, the scale should be */
/* formed from the same note type, i.e. bs or #s */
switch( note_idx )
{
case 1: case 3: case 6: case 8: case 10: /* accidentals */
dflt_note_type = note_type;
}
}
else
error( argv[a], "is not a valid note!" );
}
else /* subsequent args to -i option should be intervals */
{
if( sscanf( argv[++a], "%hu", &interval ) == 1 )
{
/* determine new note_idx from last note_idx */
note_idx = note_index(scale[i-1]) + (short)interval;
while( note_idx > 11 ) /* correct any overflow */
note_idx =- 12;
scale[i++] = chrom[dflt_note_type][note_idx];
}
else
error( argv[a], "is not a valid interval!" );
}
}
num_notes = i;
}
else if( streq(argv[a], OP_NOTES) )
{
i = 0;
while( (a+1 < argc) && not_option(argv[a+1]) )
{
/* convert case if needed */
if( islower(*(argv[++a])) )
*(argv[a]) = toupper( *(argv[a]) );
if( note_index(argv[a]) >= 0 ) /* valid note? */
scale[i++] = argv[a];
else
error( argv[a], "is not a valid note!" );
}
num_notes = i;
}
} /* end of argc loop */
/* print scale */
printf( "Scale =" );
for( i=0; i < num_notes; i++ )
printf( " %s", scale[i] );
printf( " \n" );
print_fretbd( scale );
exit(0);
}
/* ********************************************************************** */
void error( item, message )
char *item, *message;
/* Print error message, help message, and exit. */
{
fprintf( stderr," %s %s\n", item, message );
fprintf( stderr, HELP_MESSAGE );
exit(-1);
}
/* ********************************************************************** */
short note_index( note )
char *note;
/* Returns the chromatic scale index of note and sets note_type
* if note is an accidental; returns -1 if note is not a member
* of the chromatic scale.
*/
{
short i;
for( i=0; i < 12; i++ )
{
note_type = FLATS;
if( streq(note, chrom[note_type][i]) )
return(i);
note_type = SHARPS;
if( streq(note, chrom[note_type][i]) )
return(i);
}
return(-1);
}
/* ********************************************************************** */
void print_fretbd( scale )
char *scale[];
/* Print fretboard, labeling notes in scale[]. */
{
char *note;
register unsigned short string, fret_idx, fret;
printf( NECK_INDEX );
for( string=1; string <= NUM_STRINGS; string++ )
{
switch( string )
{
case 2: fret_idx = 11; break; /* B */
case 3: fret_idx = 7; break; /* G */
case 4: fret_idx = 2; break; /* D */
case 5: fret_idx = 9; break; /* A */
default: fret_idx = 4; break; /* E */
}
for( fret=0; fret < NUM_FRETS; fret++ )
{
note = get_note( fret_idx, scale );
print_note( note, fret );
fret_idx++;
while( fret_idx > 11 )
fret_idx -= 12;
}
printf( "\n" );
}
}
/* ********************************************************************** */
char *get_note( fret_idx, scale )
unsigned short fret_idx;
char *scale[];
/* Returns note if chrom[][fret_idx] is a member of scale[];
* returns "-" if chrom[][fret_idx] is not a member of scale[].
*/
{
register unsigned short i;
for( i=0; i < num_notes; i++ )
{
if( streq( scale[i], chrom[FLATS][fret_idx] ) ||
streq( scale[i], chrom[SHARPS][fret_idx] ) )
return( scale[i] );
}
return( "-" );
}
/* ********************************************************************** */
void print_note( note, fret )
char *note;
unsigned short fret;
/* Prints note or specified pos_mark_char, then proper fill chars. */
{
if( streq( note, "-" ) || (pos_mark_char == '\0') )
{
printf( "%s", note );
/* if note is a single-char string, print "-" */
if( (fret > 0) && (*(note + 1) == '\0') )
printf( "-" );
}
else
{
printf( "%c", pos_mark_char );
if( fret > 0 )
printf( "-" );
}
switch( fret ) /* print fret indicators */
{
case 0: printf( "||-" ); return;
case 19: printf( "|" ); return;
default: printf( "|-" ); return;
}
}
/* ******************************* END ********************************** */